﻿using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;
using System.Reflection;

namespace EasyXaf.ObjectSpaces.OData;

public class ODataObjectSpaceProvider : IObjectSpaceProvider, IDisposable
{
    private ITypesInfo _typesInfo;

    private ODataTypeInfoSource _typeInfoSource;

    public ITypesInfo TypesInfo => _typesInfo;

    public IEntityStore EntityStore => _typeInfoSource;

    public Uri ServiceRoot { get; }

    public string ConnectionString { get; set; }

    public Type ModuleInfoType => null;

    public SchemaUpdateMode SchemaUpdateMode { get; set; }

    public CheckCompatibilityType? CheckCompatibilityType { get; set; }

    public IServiceProvider ServiceProvider { get; }

    public ODataObjectSpaceProvider(IServiceProvider serviceProvider, ITypesInfo typesInfo, ODataTypeInfoSource typeInfoSource, Uri serviceRoot)
    {
        ServiceProvider = serviceProvider;
        ServiceRoot = serviceRoot;

        _typesInfo = typesInfo;
        _typeInfoSource = typeInfoSource ?? ((TypesInfo)typesInfo).GetOrAddEntityStore((ti) => new ODataTypeInfoSource(ti));

        var entityStores = ((IEntityStore[])typeof(TypesInfo)
            .GetField("entityStores", BindingFlags.Instance | BindingFlags.NonPublic)
            .GetValue(typesInfo))
            .ToList();

        entityStores.Remove(_typeInfoSource);
        entityStores.Insert(0, _typeInfoSource);

        typeof(TypesInfo)
            .GetField("entityStores", BindingFlags.Instance | BindingFlags.NonPublic)
            .SetValue(typesInfo, entityStores.ToArray());
    }

    public ODataObjectSpaceProvider(IServiceProvider serviceProvider, Uri serviceRoot)
        : this(serviceProvider, XafTypesInfo.Instance, null, serviceRoot)
    {
    }

    public IObjectSpace CreateObjectSpace()
    {
        return new ODataObjectSpace(ServiceProvider, _typesInfo, _typeInfoSource, ServiceRoot);
    }

    public IObjectSpace CreateUpdatingObjectSpace(bool allowUpdateSchema)
    {
        throw new NotImplementedException();
    }

    public void UpdateSchema()
    {
        throw new NotImplementedException();
    }

    public virtual void Dispose()
    {
        _typesInfo = null;
        _typeInfoSource = null;

        GC.SuppressFinalize(this);
    }
}
